package com.zhou.core.jdbc;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by zhouyongjun on 2020/7/14
 */
public class SpringJdbcService {
    private static SpringJdbcService instance = new SpringJdbcService();
    private SpringJdbcService(){}
    Map<String,DruidDataSource> dataSourceMap = new HashMap<>();
    Map<String,JdbcTemplate> jdbcTemplateMap = new HashMap<>();
    private static final Logger logger = LoggerFactory.getLogger(SpringJdbcService.class);
    public static SpringJdbcService getInstance() {
        return instance;
    }

    /**
     * 通过指定参数链接
     * @param config
     * @return
     * @throws SQLException
     */
    public JdbcTemplate connect(GTJdbcConfig config) throws SQLException {
        JdbcTemplate jdbcTemplate = null;
        String key = generateKey(config.getUrl());
        if (jdbcTemplateMap.get(key) != null)
        {
            jdbcTemplate = jdbcTemplateMap.get(key);
        }
        if (jdbcTemplate != null && !jdbcTemplate.getDataSource().getConnection().isClosed())
        {
            return jdbcTemplate;
        }
        //创建数据源连接池
        DataSource dataSource = getDataSource(config);
        //创建jdbc模板
        jdbcTemplate = new JdbcTemplate(dataSource);

        //通过api操作执行sql
//        jdbcTemplate.update("insert into student(stu_name,stu_pwd) values(?,?);", "jack","46asd4634");
//        List<Map<String,Object>> list = jdbcTemplate.queryForList("select * from server");
//        System.out.println(JSON.toJSONString(list));
        jdbcTemplateMap.put(key,jdbcTemplate);

        return jdbcTemplate;
    }

    /**
     * https://xuzhongcn.github.io/spring/Spring04.html#header-n448
     * 编程式的事务管理
     * @param dataSource
     * @return
     */
    public TransactionTemplate transactionTemplate(DataSource dataSource)
    {
        TransactionTemplate transactionTemplate =new TransactionTemplate();
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
        transactionTemplate.setTransactionManager(transactionManager);
        return transactionTemplate;
    }



    /**
     * 通过配置文件链接
     * @param classpathFileNameXml
     * @param beanName
     * @return
     * @throws SQLException
     */
    public JdbcTemplate connect(String classpathFileNameXml,String beanName) throws SQLException {
        JdbcTemplate jdbcTemplate = null;
        if (jdbcTemplateMap.get(beanName) != null)
        {
            jdbcTemplate = jdbcTemplateMap.get(beanName);
        }
        if (jdbcTemplate != null && !jdbcTemplate.getDataSource().getConnection().isClosed())
        {
            return jdbcTemplate;
        }
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(classpathFileNameXml);
        jdbcTemplate  =  applicationContext.getBean(beanName,JdbcTemplate.class);
        jdbcTemplateMap.put(beanName,jdbcTemplate);
        return jdbcTemplate;
    }

    public DataSource getDataSource(GTJdbcConfig config) throws SQLException {
        String key = generateKey(config.getUrl());
        DruidDataSource dataSource = dataSourceMap.get(key);
        if (dataSource != null && !dataSource.isClosed())
        {
            return dataSource;
        }
        dataSource = new DruidDataSource();
        dataSource.setUsername(config.getUser());
        dataSource.setPassword(config.getPwd());
        dataSource.setUrl(config.getUrl());
        dataSource.setDriverClassName(config.getDriverClassName());

        if (config.getExtraConfigMaps() != null)
        {
            DruidDataSourceFactory.config(dataSource,config.getExtraConfigMaps());
        }
        dataSourceMap.put(key,dataSource);
        return dataSource;
    }

    private String generateKey(String url) {
        String key = url;
        int index = key.indexOf("?");
        if (index > 0)
        {
            key =  url.substring(0,index);
        }
        return key;
    }

    public void close()
        {
            try {
                for (DruidDataSource dataSource : dataSourceMap.values())
                {
                    try {
                        dataSource.close();
                    } catch (Exception e) {
                        logger.error("",e);
                    }
                }
                dataSourceMap.clear();
                jdbcTemplateMap.clear();
            } catch (Exception e) {
                logger.error("",e);
            }
        }

}
